import { ACCESS_TOKEN_PLACEHOLDER } from '~/config/constants'

import { PropertyOperator } from '../../types'
import { HogFunctionType } from '../types'

/**
 * Hog functions are largely generated and built in the django service, making it tricky to test on this side.
 * As such we have a bunch of prebuilt examples here for usage in tests.
 */

export const HOG_EXAMPLES: Record<string, Pick<HogFunctionType, 'hog' | 'bytecode' | 'type'>> = {
    simple_fetch: {
        type: 'destination',
        hog: "let res := fetch(inputs.url, {\n  'headers': inputs.headers,\n  'body': inputs.body,\n  'method': inputs.method\n});\n\nprint('Fetch response:', res)",
        bytecode: [
            '_h',
            32,
            'headers',
            32,
            'headers',
            32,
            'inputs',
            1,
            2,
            32,
            'body',
            32,
            'body',
            32,
            'inputs',
            1,
            2,
            32,
            'method',
            32,
            'method',
            32,
            'inputs',
            1,
            2,
            42,
            3,
            32,
            'url',
            32,
            'inputs',
            1,
            2,
            2,
            'fetch',
            2,
            36,
            0,
            32,
            'Fetch response:',
            2,
            'print',
            2,
            35,
            35,
        ],
    },
    recursive_fetch: {
        type: 'destination',
        hog: "for (let i := 0; i < 10; i := i + 1) {\n  fetch(inputs.url, {\n    'headers': inputs.headers,\n    'body': inputs.body,\n    'method': inputs.method\n  });\n}",
        bytecode: [
            '_h',
            33,
            0,
            33,
            10,
            36,
            0,
            15,
            40,
            45,
            32,
            'headers',
            32,
            'headers',
            32,
            'inputs',
            1,
            2,
            32,
            'body',
            32,
            'body',
            32,
            'inputs',
            1,
            2,
            32,
            'method',
            32,
            'method',
            32,
            'inputs',
            1,
            2,
            42,
            3,
            32,
            'url',
            32,
            'inputs',
            1,
            2,
            2,
            'fetch',
            2,
            35,
            33,
            1,
            36,
            0,
            6,
            37,
            0,
            39,
            -52,
            35,
        ],
    },
    malicious_function: {
        type: 'destination',
        hog: "fn fibonacci(number) {\n    print('I AM FIBONACCI')\n    if (number < 2) {\n        return number;\n    } else {\n        return fibonacci(number - 1) + fibonacci(number - 2);\n    }\n}\nprint(f'fib {fibonacci(30)}');",
        bytecode: [
            '_h',
            41,
            'fibonacci',
            1,
            38,
            32,
            'I AM FIBONACCI',
            2,
            'print',
            1,
            35,
            33,
            2,
            36,
            0,
            15,
            40,
            5,
            36,
            0,
            38,
            39,
            18,
            33,
            2,
            36,
            0,
            7,
            2,
            'fibonacci',
            1,
            33,
            1,
            36,
            0,
            7,
            2,
            'fibonacci',
            1,
            6,
            38,
            31,
            38,
            33,
            30,
            2,
            'fibonacci',
            1,
            32,
            'fib ',
            2,
            'concat',
            2,
            2,
            'print',
            1,
            35,
        ],
    },

    input_printer: {
        type: 'destination',
        hog: "// I print all of the inputs\n\nprint(inputs.input_1)\nprint({'nested': inputs.secret_input_2})\nprint(inputs.secret_input_2)\nprint(f'substring: {inputs.secret_input_3}')\nprint(inputs)",
        bytecode: [
            '_h',
            32,
            'input_1',
            32,
            'inputs',
            1,
            2,
            2,
            'print',
            1,
            35,
            32,
            'nested',
            32,
            'secret_input_2',
            32,
            'inputs',
            1,
            2,
            42,
            1,
            2,
            'print',
            1,
            35,
            32,
            'secret_input_2',
            32,
            'inputs',
            1,
            2,
            2,
            'print',
            1,
            35,
            32,
            'secret_input_3',
            32,
            'inputs',
            1,
            2,
            32,
            'substring: ',
            2,
            'concat',
            2,
            2,
            'print',
            1,
            35,
            32,
            'inputs',
            1,
            1,
            2,
            'print',
            1,
            35,
        ],
    },
    posthog_capture: {
        type: 'destination',
        hog: "postHogCapture({\n    'event': f'{event.event} (copy)',\n    'distinct_id': event.distinct_id,\n    'properties': {}\n})",
        bytecode: [
            '_h',
            32,
            'event',
            32,
            ' (copy)',
            32,
            'event',
            32,
            'event',
            1,
            2,
            2,
            'concat',
            2,
            32,
            'distinct_id',
            32,
            'distinct_id',
            32,
            'event',
            1,
            2,
            32,
            'properties',
            42,
            0,
            42,
            3,
            2,
            'postHogCapture',
            1,
            35,
        ],
    },
}

export const HOG_INPUTS_EXAMPLES: Record<string, Pick<HogFunctionType, 'inputs' | 'inputs_schema'>> = {
    simple_fetch: {
        inputs_schema: [
            { key: 'url', type: 'string', label: 'Webhook URL', secret: false, required: true },
            { key: 'body', type: 'json', label: 'JSON body', secret: false, required: true },
            {
                key: 'method',
                type: 'choice',
                label: 'HTTP Method',
                secret: false,
                choices: [
                    { label: 'POST', value: 'POST' },
                    { label: 'PUT', value: 'PUT' },
                    { label: 'PATCH', value: 'PATCH' },
                    { label: 'GET', value: 'GET' },
                ],
                required: true,
            },
            { key: 'headers', type: 'dictionary', label: 'Headers', secret: false, required: false },
        ],
        inputs: {
            url: {
                value: 'https://example.com/posthog-webhook',
                bytecode: ['_h', 32, 'https://example.com/posthog-webhook'],
            },
            method: { value: 'POST' },
            headers: {
                value: { version: 'v={event.properties.$lib_version}' },
                bytecode: {
                    version: ['_h', 32, '$lib_version', 32, 'properties', 32, 'event', 1, 3, 32, 'v=', 2, 'concat', 2],
                },
            },
            body: {
                value: {
                    event: '{event}',
                    groups: '{groups}',
                    nested: { foo: '{event.url}' },
                    person: '{person}',
                    event_url: "{f'{event.url}-test'}",
                },
                bytecode: {
                    event: ['_h', 32, 'event', 1, 1],
                    groups: ['_h', 32, 'groups', 1, 1],
                    nested: { foo: ['_h', 32, 'url', 32, 'event', 1, 2] },
                    person: ['_h', 32, 'person', 1, 1],
                    event_url: ['_h', 32, '-test', 32, 'url', 32, 'event', 1, 2, 2, 'concat', 2],
                },
            },
        },
    },
    simple_fetch_with_oauth: {
        inputs_schema: [
            { key: 'oauth', type: 'integration', label: 'OAuth', secret: false, required: true, integration: 'oauth' },
            { key: 'url', type: 'string', label: 'Webhook URL', secret: false, required: true },
            { key: 'body', type: 'json', label: 'JSON body', secret: false, required: true },
            {
                key: 'method',
                type: 'choice',
                label: 'HTTP Method',
                secret: false,
                choices: [
                    { label: 'POST', value: 'POST' },
                    { label: 'PUT', value: 'PUT' },
                    { label: 'PATCH', value: 'PATCH' },
                    { label: 'GET', value: 'GET' },
                ],
                required: true,
            },
            { key: 'headers', type: 'dictionary', label: 'Headers', secret: false, required: false },
        ],
        inputs: {
            oauth: {
                value: {
                    access_token: ACCESS_TOKEN_PLACEHOLDER + '123',
                },
                bytecode: ['_h', 32, ACCESS_TOKEN_PLACEHOLDER, 32, '123'],
            },
            url: {
                value: 'https://example.com/posthog-webhook?access_token={inputs.oauth.access_token}',
                bytecode: [
                    '_h',
                    32,
                    'https://example.com/posthog-webhook',
                    32,
                    'access_token',
                    32,
                    'inputs',
                    1,
                    2,
                    32,
                    'oauth',
                    1,
                    2,
                ],
            },
            method: { value: 'POST' },
            headers: {
                value: {
                    version: 'v={event.properties.$lib_version}',
                    access_token: '{inputs.oauth.access_token}',
                },
                bytecode: {
                    version: ['_h', 32, '$lib_version', 32, 'properties', 32, 'event', 1, 3, 32, 'v=', 2, 'concat', 2],
                    access_token: ['_h', 32, 'access_token', 32, 'inputs', 1, 2, 32, 'oauth', 1, 2],
                },
            },
            body: {
                value: {
                    event: '{event}',
                    groups: '{groups}',
                    nested: { foo: '{event.url}' },
                    person: '{person}',
                    event_url: "{f'{event.url}-test'}",
                    access_token: '{inputs.oauth.access_token}',
                },
                bytecode: {
                    event: ['_h', 32, 'event', 1, 1],
                    groups: ['_h', 32, 'groups', 1, 1],
                    nested: { foo: ['_h', 32, 'url', 32, 'event', 1, 2] },
                    person: ['_h', 32, 'person', 1, 1],
                    event_url: ['_h', 32, '-test', 32, 'url', 32, 'event', 1, 2, 2, 'concat', 2],
                    access_token: ['_h', 32, 'access_token', 32, 'inputs', 1, 2, 32, 'oauth', 1, 2],
                },
            },
        },
    },
    simple_google_fetch: {
        inputs_schema: [
            { key: 'url', type: 'string', label: 'Webhook URL', secret: false, required: true },
            { key: 'body', type: 'json', label: 'JSON body', secret: false, required: true },
            {
                key: 'method',
                type: 'choice',
                label: 'HTTP Method',
                secret: false,
                choices: [
                    { label: 'POST', value: 'POST' },
                    { label: 'PUT', value: 'PUT' },
                    { label: 'PATCH', value: 'PATCH' },
                    { label: 'GET', value: 'GET' },
                ],
                required: true,
            },
            { key: 'headers', type: 'dictionary', label: 'Headers', secret: false, required: false },
        ],
        inputs: {
            url: {
                value: 'https://googleads.googleapis.com/',
                bytecode: ['_h', 32, 'https://googleads.googleapis.com/'],
            },
            method: { value: 'POST' },
            headers: {
                value: { version: 'v={event.properties.$lib_version}' },
                bytecode: {
                    version: ['_h', 32, '$lib_version', 32, 'properties', 32, 'event', 1, 3, 32, 'v=', 2, 'concat', 2],
                },
            },
            body: {
                value: {
                    event: '{event}',
                    groups: '{groups}',
                    nested: { foo: '{event.url}' },
                    person: '{person}',
                    event_url: "{f'{event.url}-test'}",
                },
                bytecode: {
                    event: ['_h', 32, 'event', 1, 1],
                    groups: ['_h', 32, 'groups', 1, 1],
                    nested: { foo: ['_h', 32, 'url', 32, 'event', 1, 2] },
                    person: ['_h', 32, 'person', 1, 1],
                    event_url: ['_h', 32, '-test', 32, 'url', 32, 'event', 1, 2, 2, 'concat', 2],
                },
            },
        },
    },
    secret_inputs: {
        inputs_schema: [
            {
                key: 'input_1',
                type: 'string',
                label: 'input_1',
                secret: false,
                required: false,
            },
            {
                key: 'secret_input_2',
                type: 'dictionary',
                label: 'secret_input_2',
                secret: true,
                default: {},
                required: true,
            },
            {
                key: 'secret_input_3',
                type: 'string',
                label: 'secret_input_3',
                secret: true,
                required: true,
            },
        ],
        inputs: {
            input_1: { value: 'test', bytecode: ['_h', 32, 'test'] },
            secret_input_2: {
                value: { foo: 'bar', null: null, bool: false },
                bytecode: { foo: ['_h', 32, 'bar'], null: ['_h', 32, null], bool: ['_h', 32, false] },
            },
            secret_input_3: { value: 'super secret', bytecode: ['_h', 32, 'super secret'] },
        },
    },
    none: {
        inputs_schema: [],
        inputs: {},
    },
}

export const HOG_FILTERS_EXAMPLES: Record<string, Pick<HogFunctionType, 'filters'>> = {
    no_filters: { filters: { events: [], actions: [], bytecode: ['_h', 29] } },
    broken_filters: { filters: { events: [], actions: [], bytecode: ['_H', 1, 29, 35, 35, 35] } },
    pageview_or_autocapture_filter: {
        filters: {
            events: [
                {
                    id: '$pageview',
                    name: '$pageview',
                    type: 'events',
                    order: 0,
                    properties: [
                        { key: '$current_url', type: 'event', value: 'posthog', operator: PropertyOperator.IContains },
                    ],
                },
                { id: '$autocapture', name: '$autocapture', type: 'events', order: 1 },
            ],
            actions: [],
            bytecode: [
                '_h',
                32,
                '$autocapture',
                32,
                'event',
                1,
                1,
                11,
                3,
                1,
                32,
                '%posthog%',
                32,
                '$current_url',
                32,
                'properties',
                1,
                2,
                18,
                32,
                '$pageview',
                32,
                'event',
                1,
                1,
                11,
                3,
                2,
                4,
                2,
            ],
        },
    },
    elements_text_filter: {
        filters: {
            actions: [],
            bytecode: [
                '_H',
                1,
                32,
                '$autocapture',
                32,
                'event',
                1,
                1,
                11,
                52,
                'lambda',
                1,
                0,
                6,
                32,
                '%reload%',
                36,
                0,
                18,
                38,
                53,
                0,
                32,
                'elements_chain_texts',
                1,
                1,
                2,
                'arrayExists',
                2,
                3,
                2,
                4,
                1,
            ],
            events: [
                {
                    id: '$autocapture',
                    name: '$autocapture',
                    order: 0,
                    properties: [
                        { key: 'text', operator: PropertyOperator.IContains, type: 'element', value: 'reload' },
                    ],
                    type: 'events',
                },
            ],
            filter_test_accounts: false,
        },
    },
    elements_href_filter: {
        filters: {
            actions: [],
            bytecode: [
                '_H',
                1,
                32,
                '$autocapture',
                32,
                'event',
                1,
                1,
                11,
                32,
                '%/project/1/activity/explore%',
                32,
                'elements_chain_href',
                1,
                1,
                18,
                3,
                2,
            ],
            events: [
                {
                    id: '$autocapture',
                    name: '$autocapture',
                    order: 0,
                    properties: [
                        {
                            key: 'href',
                            operator: PropertyOperator.IContains,
                            type: 'element',
                            value: '/project/1/activity/explore',
                        },
                    ],
                    type: 'events',
                },
            ],
            filter_test_accounts: false,
        },
    },
    elements_tag_and_id_filter: {
        filters: {
            actions: [],
            bytecode: [
                '_H',
                1,
                32,
                '$autocapture',
                32,
                'event',
                1,
                1,
                11,
                32,
                '(^|;)a.*?attr_id="homelink".*?([-_a-zA-Z0-9\\.:"= ]*?)?($|;|:([^;^\\s]*(;|$|\\s)))',
                32,
                'elements_chain',
                1,
                1,
                23,
                33,
                0,
                32,
                'elements_chain_ids',
                1,
                1,
                32,
                'homelink',
                2,
                'indexOf',
                2,
                14,
                33,
                0,
                52,
                'lambda',
                1,
                0,
                8,
                32,
                'a',
                43,
                1,
                36,
                0,
                21,
                38,
                53,
                0,
                32,
                'elements_chain_elements',
                1,
                1,
                2,
                'arrayCount',
                2,
                13,
                3,
                3,
                3,
                2,
            ],
            events: [
                {
                    id: '$autocapture',
                    name: '$autocapture',
                    order: 0,
                    properties: [
                        { key: 'selector', operator: PropertyOperator.IContains, type: 'element', value: 'div#root' },
                    ],
                    type: 'events',
                },
            ],
            filter_test_accounts: false,
        },
    },
}

export const HOG_MASK_EXAMPLES: Record<string, Pick<HogFunctionType, 'masking'>> = {
    all: {
        masking: {
            ttl: 30,
            hash: 'all',
            bytecode: ['_h', 32, 'all'],
            threshold: null,
        },
    },
    person: {
        masking: {
            ttl: 30,
            hash: '{person.id}',
            bytecode: ['_h', 32, 'id', 32, 'person', 1, 2],
            threshold: null,
        },
    },
    personAndEvent: {
        masking: {
            ttl: 30,
            hash: '{concat(person.id, event.event)}',
            bytecode: ['_H', 1, 32, 'id', 32, 'person', 1, 2, 32, 'event', 32, 'event', 1, 2, 2, 'concat', 2],
            threshold: null,
        },
    },
}

export const HOG_FLOW_MASK_EXAMPLES: Record<string, Pick<any, 'trigger_masking'>> = {
    everyTime: {
        trigger_masking: {
            ttl: 30,
            hash: 'all',
            bytecode: ['_h', 32, 'all'],
            threshold: null,
        },
    },
    oncePerTimePeriod: {
        trigger_masking: {
            ttl: 30,
            hash: '{person.id}',
            bytecode: ['_h', 32, 'id', 32, 'person', 1, 2],
            threshold: null,
        },
    },
    onceEver: {
        trigger_masking: {
            ttl: null,
            hash: '{person.id}',
            bytecode: ['_h', 32, 'id', 32, 'person', 1, 2],
            threshold: null,
        },
    },
}
